/* -----------------------------------
Brightness Controller v4.21 - The most advanced brightness and energy manager for Sony Ericsson's elfpack-enabled phone!
(c)2009 mc_kibel from CentrumSE.pl ! Visit us! 
Thanks to:
-Edgpaez (for disabling control in mediaplayer and radio)
-Zylka
-G29 (bugreport)
-SE-Developers.net and CentrumSE.pl communities for ideas

Changelog:
v1.0:
-Ability to change brightness by pressing volume up / down keys

v1.1 / v1.2:
-Disabled control, when CameraBook, AudioPlayerBook, MediaPlayerVideoBook or FMRadioBook are on.
-Small fixes

v1.3 to v3.01 not published due to a many bugs!

v3.02:
-BCFG Support!
-Inteligence AutoBacklight and EnergySaver system added!

v3.03:
-Fixed bug with manual brightness control with InteligenceAutoBacklight and EnergySaver systems

v3.04 (private):
-Big code optimization

v3.051:
-Based on v3.04
-Added ability to automatically change brightness level in CameraBook
-Now it's possible to run only one copy of elf at the same time (security).
-Support for Bookman v3 mod

v4.00
-Configurable intervals!!
--from 00:00 to xx  default: to 7:00
--from xx to yy     default: to 11:00
--from yy to zz     default: to 20:00
--from zz to 00:00 
-CheckConfig System added
--If CheckConfig system will find errors in .bcfg file, elf will be closed and default settings will be restored.

v.4.2
-Changed BCFG Structure
-Changed BCFG name from "BacklightController" to "BrightnessController" (!)
-Changed default settings in BCFG
-Small optimizations

v4.3
-Very important update! Fixed work of all systems together

v4.4
-Added A2 support :)

------------------------------------*/

#include "..\\include\Lib_Clara.h"
#include "..\\include\Dir.h"
#include "..\\include\cfg_items.h"
#include "conf_loader.h"
#include "config_data.h"

#define ELF_BCFG_CONFIG_EVENT 994

#define A1 1
#define A2 2
int Platform;

u16 timer;
BOOK * BCBook;

int hour;
unsigned int val; 
unsigned int RemainingCapacityInPercent;
unsigned int current;


typedef struct
{
  BOOK * book;
}MSG;

//-------------------- Author info----------------------------------------------
int ShowAuthorInfo(void *mess ,BOOK* book)
{
  MSG * msg = (MSG*)mess;
  MessageBox(0x6fFFFFFF,STR("Brightness Controller\n(c)2009 mc_kibel\nv4.4\nThanks to Zylka, SE-Developers & G29.\nVisit CentrumSE.pl!"),0, 1 ,10000,msg->book);
  return(1);
}
//------------------------------------------------------------------------------

//--------------------- BOOKs used in ELF---------------------------------------
int isBrightnessControllerBook(BOOK * book)
{
  if(!strcmp(book->xbook->name,"BrightnessController")) 
    return 1;
  return 0;
}

int isImageViewerBook (BOOK * book)
{
  if(!strcmp(book->xbook->name,"ImageViewerBook"))
    return 1;
  return 0;
}

int isCamBook (BOOK * book)
{
  if(!strcmp(book->xbook->name,"CameraBook"))
    return 1;
  return 0;
}
//------------------------------------------------------------------------------

//---------------Functions used in elf------------------------------------------

int DISPLAY_SetBr(int param1, int param2)
{
  if (Platform==A1)
    Display_SetBrightness(param1,param2);
  else if (Platform==A2)
    Display_SetBrightness(param2,param1);
  
  return 0;
}

int GetBatteryLevel (void)
{
  BATT Battery;
  GetBatteryState(NULL , &Battery);
  RemainingCapacityInPercent = Battery.RemainingCapacityInPercent;
  return (RemainingCapacityInPercent);
}


void CheckConfig (void)
{
  if ( EndSecInt <= EndFirstInt || EndThirdInt <= EndSecInt || EndThirdInt <= EndFirstInt )
  {
    FileDelete (GetDir(DIR_ELFS_CONFIG|MEM_EXTERNAL) ,L"BrightnessController.bcfg" , 0 );
    FileDelete (GetDir(DIR_ELFS_CONFIG|MEM_INTERNAL) ,L"BrightnessController.bcfg" , 0 );
    MessageBox(0x6fFFFFFF,STR("Error occurs in .bcfg file! Brightness Controller closed."),0, 1 ,1000,0); 
    FreeBook(FindBook(isBrightnessControllerBook));
    Timer_Kill( &timer );
  }
}


void InitIncreasing (void)
{
  current = Display_GetBrightness(0);
  DISPLAY_SetBr(0, current+10);
  if(IS_ENABLED == 1) 
    MessageBox(0x6fFFFFFF,STR("Brightness Controller v4.4\n\n Brightness increased."),0, 1 ,1000,0); 
}

void InitDecreasing (void)
{
  current = Display_GetBrightness(0);
  DISPLAY_SetBr(0, current-10);
  if(IS_ENABLED == 1) 
    MessageBox(0x6fFFFFFF,STR("Brightness Controller v4.4\n\n Brightness decreased"),0, 1 ,1000,0); 
}

int NewKey(int key, int r1 , int mode)
{
  if(!SmartAB && !EnergySaver)
  {
    if (key==(KEY1) && mode==(KEYMODE1) && Display_GetBrightness(0) < 100) 
      InitIncreasing();
    else if (key==(KEY2) && mode==(KEYMODE2) && Display_GetBrightness(0) > 10) 
      InitDecreasing();
  }
  else if(!SmartAB && EnergySaver)
  {
    GetBatteryLevel();
    if(RemainingCapacityInPercent > (BattPercent))
    {
      if (key==(KEY1) && mode==(KEYMODE1) && Display_GetBrightness(0) < 100) 
        InitIncreasing();
      else if (key==(KEY2) && mode==(KEYMODE2) && Display_GetBrightness(0) > 10) 
        InitDecreasing();
    }
  }
  return 0;
}

int ManualMode(void)
{
  if(DISABLE_CONTROL==1) 
  {
    BOOK * MP = FindBook(isAudioPlayerBook());
    BOOK * FM = FindBook(isFmRadioBook());
    BOOK * CS = FindBook(isCamBook);
    BOOK * VD = FindBook(isMediaPlayerVideoBook());
    BOOK * SS = FindBook(isScreenSaverBook());
    BOOK * IMV = FindBook(isImageViewerBook);
    
    if(MP || FM || CS || VD || SS || IMV) 
      ModifyKeyHook(NewKey,0);
    else 
      ModifyKeyHook(NewKey,1);
  } 
  else
    ModifyKeyHook(NewKey,1);
  
  return 0;
}


int GetTime (void)
{
  DATETIME Date_and_time;
  REQUEST_DATEANDTIME_GET (0, &Date_and_time); 
  hour = Date_and_time.time.hour; 
  return (hour);
}


void InitInteligenceAutoBacklight (void)
{
  GetTime();
  
  if ( hour>=0 && hour<EndFirstInt )
    val = ValueOne;
  else if ( hour >= EndFirstInt && hour < EndSecInt ) 
    val = ValueTwo;
  else if ( hour >= EndSecInt && hour < EndThirdInt ) 
    val = ValueThree;
  else if ( hour >= EndThirdInt && hour > 0 ) 
    val = ValueFour;
  
  DISPLAY_SetBr(0, (val));
}
//------------------------------------------------------------------------------


int TerminateElf(void * ,BOOK* book)
{
  ModifyKeyHook(NewKey,0);
  Timer_Kill(&timer);
  FreeBook(book);
  return(1);
}

static int ReconfigElf(void *mess ,BOOK *book)
{
  RECONFIG_EVENT_DATA *reconf=(RECONFIG_EVENT_DATA *)mess;
  int result=0;
  if (wstrcmpi(reconf->path,successed_config_path)==0 && wstrcmpi(reconf->name,successed_config_name)==0)
  {
    InitConfig();
    result=1;
  }
  return(result);
}

int onBcfgConfig(void* mess,BOOK* b)
{
  FSTAT _fstat;
  wchar_t path[256];
  
  if(fstat(GetDir(DIR_ELFS|MEM_INTERNAL),L"BcfgEdit.elf",&_fstat)==0)
  {
    wstrcpy(path,GetDir(DIR_ELFS|MEM_INTERNAL));
  }
  else if(fstat(GetDir(DIR_ELFS|MEM_EXTERNAL),L"BcfgEdit.elf",&_fstat)==0)
  {
    wstrcpy(path,GetDir(DIR_ELFS|MEM_EXTERNAL));
  }
  else
  {
    MessageBox(0x6FFFFFFF, STR("BcfgEdit.elf not found!"), 0, 1 ,5000, 0);
    return (1);
  }
  wstrcat(path,L"/BcfgEdit.elf");
  elfload(path,(void*)successed_config_path,(void*)successed_config_name,0);
  return (1);
}

const PAGE_MSG BC_PageEvents[]@ "DYN_PAGE" ={
  ELF_TERMINATE_EVENT , TerminateElf,
  ELF_SHOW_INFO_EVENT  , ShowAuthorInfo,
  ELF_RECONFIG_EVENT,    ReconfigElf,
  ELF_BCFG_CONFIG_EVENT,   onBcfgConfig,
  NIL_EVENT_TAG,           NULL
};
PAGE_DESC base_page ={"BC_BasePage",0,BC_PageEvents};


void elf_exit(void)
{
  ModifyKeyHook(NewKey,0);
  Timer_Kill(&timer);
  kill_data(&ELF_BEGIN, (void(*)(void*))mfree_adr());
}

void onCloseBCBook(BOOK * book)
{
  if (book)
  {
    Timer_Kill(&timer);
    SUBPROC(elf_exit);
  }
}

BOOK * CreateBCBook()
{
  BCBook= new BOOK;
  CreateBook(BCBook,onCloseBCBook,&base_page,"BrightnessController",-1,0);
  return(BCBook);
}

void onTimer (u16 unk , void * data)
{
  {
    //Important: CamBook, CamChange, EnergySaver, SmartAB
    CheckConfig();
    BOOK * CamBook = FindBook(isCamBook);
    
    /*
    000 +
    001 +
    010 +
    011 +
    100 +
    101 +
    110 +
    111 +
    */
    
    if (SmartAB && EnergySaver && CamChange) //111
    {
      GetBatteryLevel();
      
      if (!CamBook)
      {
        if (RemainingCapacityInPercent <= (BattPercent))
          DISPLAY_SetBr ( 0, (DecreaseTo) );
        else
          InitInteligenceAutoBacklight();
      }
      else
        DISPLAY_SetBr ( 0, (CamLevel) );
    }
    else if (!SmartAB && EnergySaver && CamChange) // 011
    {
      GetBatteryLevel();
      
      if (!CamBook)
      {
        if (RemainingCapacityInPercent <= (BattPercent))
          DISPLAY_SetBr ( 0, (DecreaseTo) );
      }
      else
        DISPLAY_SetBr ( 0, (CamLevel) );
    }
    else if (!SmartAB && !EnergySaver && CamChange) //001
    {
      if (CamBook)
        DISPLAY_SetBr ( 0, (CamLevel) );
    }
    else if (SmartAB && !EnergySaver && !CamChange) //100
    {
      InitInteligenceAutoBacklight();
    }
    else if (SmartAB && !EnergySaver && CamChange) //101
    {
      if (!CamBook)
        InitInteligenceAutoBacklight();
      else
        DISPLAY_SetBr ( 0, (CamLevel) );
    }
    else if (SmartAB && EnergySaver && !CamChange) //110
    {
      GetBatteryLevel();
      
      if (RemainingCapacityInPercent <= (BattPercent))
        DISPLAY_SetBr ( 0, (DecreaseTo) );
      else
        InitInteligenceAutoBacklight();
    }
    else if (!SmartAB && EnergySaver && !CamChange) //010
    {
      if (RemainingCapacityInPercent <= (BattPercent))
        DISPLAY_SetBr ( 0, (DecreaseTo) );
    }
    else if (!SmartAB && !EnergySaver && !CamChange) //000
      ManualMode();
    
    Timer_ReSet(&timer,3000,onTimer,0);
  }
}


int main (void)
{
  if (FindBook(isBrightnessControllerBook))
    MessageBox(0x6fFFFFFF,STR("BrightnessController is already working!"),0, 1 ,5000,0); 
  else 
  {
    InitConfig();
    CreateBCBook();
    int chipID = GetChipID();
    
    if (chipID==0x7100 || chipID==0x8000 || chipID==0x8040 || chipID==0x9900)
      Platform=A1;
    else
      Platform=A2;
    
    timer=Timer_Set(3000,onTimer,0);
  }
  return(0);
}
